package com.glink.manage.service.Impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.domain.ConstructionWorkAccessMonadBean;
import com.glink.manage.domain.OrgBean;
import com.glink.manage.domain.PersonAccessRelaBean;
import com.glink.manage.domain.VehicleAccessRelaBean;
import com.glink.manage.dto.constructionwork.*;
import com.glink.manage.dto.person.PersonAccessMonadPageDTO;
import com.glink.manage.dto.person.PersonManageIdDTO;
import com.glink.manage.dto.temporaryadmission.TemporaryAdmissionIdDTO;
import com.glink.manage.dto.vehicle.VehicleDelDTO;
import com.glink.manage.mapper.ConstructionWorkAccessMonadMapper;
import com.glink.manage.service.*;
import com.glink.manage.vo.constructionwork.ConstructionWorkAccessMonadDetailsVO;
import com.glink.manage.vo.constructionwork.ConstructionWorkAccessMonadPageVO;
import com.glink.manage.vo.constructionwork.ConstructionWorkListVO;
import com.glink.manage.vo.person.PersonAccessMonadPageVO;
import com.glink.manage.vo.person.PersonSimpleInfoVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionCarBaseVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionPersonBaseVO;
import com.glink.manage.vo.user.UserBaseInfoVO;
import com.glink.manage.vo.vehicle.VehicleLicensePlateVO;
import com.glink.manage.vo.ws.WarnCountVO;
import com.glink.manage.ws.WarnWebSocketService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author  qiushaoshan
 * @since 2025-01-13
 */
@Service
@Slf4j
public class ConstructionWorkAccessMonadServiceImpl extends ServiceImpl<ConstructionWorkAccessMonadMapper, ConstructionWorkAccessMonadBean> implements ConstructionWorkAccessMonadService {
    
    @Autowired
    private VehicleService vehicleService;
    
    @Autowired
    private VehicleAccessRelaService vehicleAccessRelaService;
    
    @Autowired
    private ConstructionWorkService constructionWorkService;
    
    @Autowired
    @Lazy
    private PersonManageService personManageService;
    
    @Autowired
    private PersonAccessRelaService personAccessRelaService;

    @Autowired
    private UserService userService;
    
    @Autowired
    private OrgService orgService;
    
    @Autowired
    private WarnWebSocketService warnWebSocketService;
    
    @Autowired
    @Lazy
    private BarrierGateService barrierGateService;
    
    @Autowired
    @Lazy
    private TemporaryAdmissionService temporaryAdmissionService;
    
    /**
     * 分页查询准入申请审批单
     *
     * @param dto 分页查询条件
     * @return 准入申请单
     */
    @Override
    public IPage<PersonAccessMonadPageVO> pageByAccessMonad(PersonAccessMonadPageDTO dto) {
        IPage<ConstructionWorkAccessMonadBean> personManageBeanIPage = new Page<>(dto.getPage(), dto.getSize());

        IPage<ConstructionWorkAccessMonadBean> accessMonadBeanIPage = this.lambdaQuery()
                .eq(ConstructionWorkAccessMonadBean::getAssociationObjId, dto.getAssociationObjId())
                .orderByDesc(ConstructionWorkAccessMonadBean::getCreateTime)
                .orderByAsc(ConstructionWorkAccessMonadBean::getObjId)
                .page(personManageBeanIPage);

        IPage<PersonAccessMonadPageVO> pageVOIPage = new Page<>(accessMonadBeanIPage.getCurrent(), accessMonadBeanIPage.getSize(), accessMonadBeanIPage.getTotal());
        List<PersonAccessMonadPageVO> pageVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accessMonadBeanIPage.getRecords())) {
            accessMonadBeanIPage.getRecords().forEach(accessMonadBean -> {
                PersonAccessMonadPageVO accessMonadPageVO = new PersonAccessMonadPageVO();
                accessMonadPageVO.setAccessStatus(accessMonadBean.getAccessStatus());
                accessMonadPageVO.setConstructionWorkObjId(accessMonadBean.getConstructionWorkObjId());
                accessMonadPageVO.setOpinion(accessMonadBean.getOpinion() == null ? "" : accessMonadBean.getOpinion());
                accessMonadPageVO.setObjId(accessMonadBean.getObjId());
                if(StringUtils.isNotBlank(accessMonadBean.getConstructionWorkObjId())){
                    String workName = constructionWorkService.findNameByObjId(accessMonadBean.getConstructionWorkObjId());
                    accessMonadPageVO.setConstructionWorkObjName(workName);
                }
            
                pageVOList.add(accessMonadPageVO);
            });
            pageVOIPage.setRecords(pageVOList);
        }
        return pageVOIPage;
    }

    /**
     * 获取下一个审批单号
     * @return 审批单号
     */
    private Integer getNextApprovalNumber(){
        String approvalNumberStr = this.baseMapper.maxApprovalNumber();
        // 不存在审批单号，则初始化默认的1
        if(StringUtils.isBlank(approvalNumberStr)){
            return 1;
        }
        
        try {
            int approvalNumber = Integer.parseInt(approvalNumberStr);
            return ++ approvalNumber;
        }catch (Exception e){
            log.info("准入审批单，获取审批单号异常，旧审批单号：{}", approvalNumberStr);
            Integer count = this.lambdaQuery().isNotNull(ConstructionWorkAccessMonadBean::getApprovalNumber).ne(ConstructionWorkAccessMonadBean::getApprovalNumber, "").count();
            if(Objects.isNull(count)){
                return 1;
            }
            
            return ++ count;
        }
    }

    /**
     * 新增准入申请
     *
     * @param dto 准入申请信息
     * @return 新增状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean insertAccessMonad(ConstructionWorkAccessMonadSaveDTO dto) throws GeneralSimpleException {

        // 是否黑名单
        boolean ifBlackList = false;
        if(StringUtils.equals(dto.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
            ifBlackList = personManageService.checkBlackList(dto.getAssociationObjId());
        }else if(StringUtils.equals(dto.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType02)){
            // 车辆
            ifBlackList = vehicleService.checkBlackList(dto.getAssociationObjId());

        }

        // 黑名单无法创建准入
        if(ifBlackList){
            throw new GeneralSimpleException("400041");
        }
        
        // 发起单位
        String userId = BaseCommonUtils.extractUserIdtByToken();
        String orgId = BaseCommonUtils.extractOrdIdByToken();
        if(StringUtils.isBlank(userId) || StringUtils.isBlank(orgId)){
            throw new GeneralSimpleException("400042");
        }
        // 用户信息
        UserBaseInfoVO userBaseInfoVO = userService.findById(userId);
        if(Objects.isNull(userBaseInfoVO)){
            throw new GeneralSimpleException("400043");
        }
        // 是否是参建单位（根据角色信息判断）
        boolean checkCJDWByUser = userService.checkCJDWByUser();
        boolean generalContractingUnit = userService.checkGeneralContractingUnit();
        if(!checkCJDWByUser && !generalContractingUnit){
            throw new GeneralSimpleException("400044", userBaseInfoVO.getFullName());
        }

        List<String> accessStatus = Lists.newArrayList();
        accessStatus.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03);
        
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery()
                .eq(ConstructionWorkAccessMonadBean::getAssociationObjId, dto.getAssociationObjId())
                .eq(ConstructionWorkAccessMonadBean::getType, dto.getType())
                .eq(ConstructionWorkAccessMonadBean::getConstructionWorkObjId, dto.getConstructionWorkObjId())
                .notIn(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .list();
        
        ConstructionWorkAccessMonadBean accessMonadBean = new ConstructionWorkAccessMonadBean();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            List<String> collect = accessMonadBeanList.stream().map(ConstructionWorkAccessMonadBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
            if(StringUtils.equals(dto.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
                List<PersonAccessRelaBean> accessRelaBeanList = personAccessRelaService.lambdaQuery()
                        .eq(PersonAccessRelaBean::getPersonId, dto.getAssociationObjId())
                        .in(PersonAccessRelaBean::getConstructionWorkObjId, collect)
                        .list();
                if(CollectionUtils.isNotEmpty(accessRelaBeanList)){
                    throw new GeneralSimpleException("403001");
                }
            }else {
                List<VehicleAccessRelaBean> vehicleAccessRelaBeanList = vehicleAccessRelaService.lambdaQuery()
                        .eq(VehicleAccessRelaBean::getVehicleId, dto.getAssociationObjId())
                        .in(VehicleAccessRelaBean::getConstructionWorkObjId, collect)
                        .list();
                if(CollectionUtils.isNotEmpty(vehicleAccessRelaBeanList)){
                    throw new GeneralSimpleException("403001");
                }
            }
        }
     
        accessMonadBean.setObjId(BaseCommonUtils.generateUUID());
        accessMonadBean.setApprovalNumber(getNextApprovalNumber());
        accessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02);
        accessMonadBean.setConstructionWorkObjId(dto.getConstructionWorkObjId());
        accessMonadBean.setType(dto.getType());
        accessMonadBean.setAssociationObjId(dto.getAssociationObjId());
        // 发起单位
        accessMonadBean.setCreateUserOrgId(orgId);
        return save(accessMonadBean);
    }

    /**
     * 查询可办理准入的工程
     *
     * @param dto 查询条件
     * @return 工程信息
     */
    @Override
    public List<ConstructionWorkListVO> findWorkList(ConstructionWorkAccessMonadListDTO dto) throws GeneralSimpleException {
        List<String> accessStatus = Lists.newArrayList();
        accessStatus.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03);
        accessStatus.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus04);
        
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery()
                .eq(ConstructionWorkAccessMonadBean::getAssociationObjId, dto.getAssociationObjId())
                .eq(ConstructionWorkAccessMonadBean::getType, dto.getType())
                .notIn(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .list();
        List<String> constructiuonWorkObjIdList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            constructiuonWorkObjIdList = accessMonadBeanList.stream()
                    .map(ConstructionWorkAccessMonadBean::getConstructionWorkObjId)
                    .distinct().collect(Collectors.toList());
        }

        constructiuonWorkObjIdList = filterEffectiveWorkId(constructiuonWorkObjIdList, dto.getType(), dto.getAssociationObjId());

        return constructionWorkService.findPendingAdmissionListByObjIdNotIn(constructiuonWorkObjIdList);
    }
    
    private List<String> filterEffectiveWorkId(List<String> constructiuonWorkObjIdList, String type, String objId){
        if(CollectionUtils.isNotEmpty(constructiuonWorkObjIdList)){
            // 查询这些已经准入的审批单，是否存在记录的有效期
            if(StringUtils.equals(type, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
                List<PersonAccessRelaBean> accessRelaBeanList = personAccessRelaService.lambdaQuery()
                        .eq(PersonAccessRelaBean::getPersonId, objId).list();
                if(CollectionUtils.isNotEmpty(accessRelaBeanList)){
                    constructiuonWorkObjIdList = accessRelaBeanList.stream().map(PersonAccessRelaBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
                }
            }else {
                List<VehicleAccessRelaBean> vehicleAccessRelaBeanList = vehicleAccessRelaService.lambdaQuery().eq(VehicleAccessRelaBean::getVehicleId, objId).list();
                if(CollectionUtils.isNotEmpty(vehicleAccessRelaBeanList)){
                    constructiuonWorkObjIdList = vehicleAccessRelaBeanList.stream().map(VehicleAccessRelaBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
                }
            }
        }
        return constructiuonWorkObjIdList;
    }

    /**
     * 撤回申请单
     *
     * @param dto 申请单ID
     * @return 撤回状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean withdraw(ConstructionWorkAccessMonadWithdrawDTO dto) throws GeneralSimpleException {
        ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = this.lambdaQuery().eq(ConstructionWorkAccessMonadBean::getObjId, dto.getObjId()).one();
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            if(StringUtils.equals(constructionWorkAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus04);
                return updateById(constructionWorkAccessMonadBean);
            }else{
                throw new GeneralSimpleException("400040");
            }
          
        }
        return false;
    }

    /**
     * 查询准入工程ID
     *
     * @param associationObjId      关联ID
     * @param approvalFormType 审批单状态
     * @param accessStatus 审批类型
     * @return 工程ID
     */
    @Override
    public List<String> findWorkIdByAssociationObjIdAndTypeAndAccessStatus(String associationObjId, String approvalFormType, String accessStatus) {
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery()
                .eq(ConstructionWorkAccessMonadBean::getAssociationObjId, associationObjId)
                .eq(ConstructionWorkAccessMonadBean::getType, approvalFormType)
                .eq(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .ge(ConstructionWorkAccessMonadBean::getCycleStart, DateUtil.beginOfDay(new Date()))
                .le(ConstructionWorkAccessMonadBean::getCycleEnd, DateUtil.beginOfDay(new Date()))
                .list();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            return accessMonadBeanList.stream().map(ConstructionWorkAccessMonadBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 同意审批
     *
     * @param dto 审批单信息
     * @return 同意状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean agreeApprove(ConstructionWorkAccessMonadAgreeDTO dto) throws GeneralSimpleException {
        ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = this.lambdaQuery().eq(ConstructionWorkAccessMonadBean::getObjId, dto.getObjId()).one();
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            if(StringUtils.equals(constructionWorkAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                
                // 正式人员和正式车辆准入审批，必须选择准入周期
                if(StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01) || StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
                    if(Objects.isNull(dto.getCycleStart()) || Objects.isNull(dto.getCycleEnd()) ){
                        throw new GeneralSimpleException("400069");
                    }
                }
                
                constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);
                if(Objects.nonNull(dto.getCycleStart())){
                    constructionWorkAccessMonadBean.setCycleStart(dto.getCycleStart());
                }
                if(Objects.nonNull(dto.getCycleEnd())){
                    constructionWorkAccessMonadBean.setCycleEnd(dto.getCycleEnd());
                }
                boolean status = updateById(constructionWorkAccessMonadBean);
                if(status){
                    // 审批通过，则添加准入列表
                    if(StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
                        personManageService.saveAccessWork(constructionWorkAccessMonadBean.getAssociationObjId(), constructionWorkAccessMonadBean.getConstructionWorkObjId(), dto.getCycleStart(), dto.getCycleEnd(), constructionWorkAccessMonadBean.getObjId());
                    }else if(StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType02)){
                        //  车辆
                        vehicleService.saveAccessWork(constructionWorkAccessMonadBean.getAssociationObjId(), constructionWorkAccessMonadBean.getConstructionWorkObjId(), dto.getCycleStart(), dto.getCycleEnd(), constructionWorkAccessMonadBean.getObjId());
                    }else if(StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03)){
                        if(Objects.nonNull(dto.getCycleStart()) || Objects.nonNull(dto.getCycleEnd())){
                            temporaryAdmissionService.updateCycleByObjId(dto.getCycleStart(), dto.getCycleEnd(), constructionWorkAccessMonadBean.getAssociationObjId());
                        }
                     
                        // 人员临时准入
                        CompletableFuture.runAsync(() -> barrierGateService.issuingTemporaryPersonByPersonObjId(constructionWorkAccessMonadBean.getAssociationObjId()));
                    }else if(StringUtils.equals(constructionWorkAccessMonadBean.getType(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04)){

                        if(Objects.nonNull(dto.getCycleStart()) || Objects.nonNull(dto.getCycleEnd())){
                            temporaryAdmissionService.updateCycleByObjId(dto.getCycleStart(), dto.getCycleEnd(), constructionWorkAccessMonadBean.getAssociationObjId());
                        }
                        
                        // 车辆临时准入
                        CompletableFuture.runAsync(() -> barrierGateService.issuingTemporaryCarToBarrierGateByCarObjId(constructionWorkAccessMonadBean.getAssociationObjId()));
                    }
                }else{
                    log.error("审批单审批状态更新失败");
                    throw new GeneralSimpleException("400064");
                }
                return true;
            }else{
                log.error("审批单审批状态为待审批，无法审批通过");
                throw new GeneralSimpleException("400040");
            }

        }
        return false;
    }

    /**
     * 驳回审批
     *
     * @param dto 驳回信息
     * @return 驳回状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean rejectApprove(ConstructionWorkAccessMonadRejectDTO dto) throws GeneralSimpleException {
        ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = this.lambdaQuery().eq(ConstructionWorkAccessMonadBean::getObjId, dto.getObjId()).one();
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            if(StringUtils.equals(constructionWorkAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03);
                constructionWorkAccessMonadBean.setOpinion(dto.getOpinion());
                return updateById(constructionWorkAccessMonadBean);
            }else{
                throw new GeneralSimpleException("400040");
            }

        }
        return false;
    }

    /**
     * 查询申请单详情
     *
     * @param dto 申请单ID
     * @return 申请单详情
     */
    @Override
    public ConstructionWorkAccessMonadDetailsVO findDetailById(ConstructionWorkAccessMonadIdDTO dto) throws GeneralSimpleException {
        ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = this.lambdaQuery().eq(ConstructionWorkAccessMonadBean::getObjId, dto.getObjId()).one();
        ConstructionWorkAccessMonadDetailsVO detailsVO = new ConstructionWorkAccessMonadDetailsVO();
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            detailsVO.setMonadObjId(constructionWorkAccessMonadBean.getObjId());
            detailsVO.setCycleStart(constructionWorkAccessMonadBean.getCycleStart());
            detailsVO.setCycleEnd(constructionWorkAccessMonadBean.getCycleEnd());
            
            String type = constructionWorkAccessMonadBean.getType();
            if(StringUtils.equals(type, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01)){
                // 人员
                try {
                    PersonSimpleInfoVO personSimpleInfoVO = personManageService.findById(new PersonManageIdDTO(constructionWorkAccessMonadBean.getAssociationObjId()));
                    detailsVO.setPersonInfoVO(personSimpleInfoVO);
                }catch (Exception e){
                    log.error("准入审批单，查询用户详细信息失败, 用户ID：{}", constructionWorkAccessMonadBean.getAssociationObjId());
                }
            }else if(StringUtils.equals(type, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType02)){
                //  车辆 objid
                try {
                    VehicleLicensePlateVO vehicleLicensePlateVO = vehicleService.findById(new VehicleDelDTO(constructionWorkAccessMonadBean.getAssociationObjId()));
                    detailsVO.setVehicleInfoVO(vehicleLicensePlateVO);
                }catch (Exception e){
                    log.error("准入审批单，查询用户详细信息失败, 设备ID：{}", constructionWorkAccessMonadBean.getAssociationObjId());
                }
            }else if(StringUtils.equals(type, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03)){
                TemporaryAdmissionPersonBaseVO admissionPersonBaseVO = temporaryAdmissionService.findByPerson(new TemporaryAdmissionIdDTO(constructionWorkAccessMonadBean.getAssociationObjId()));
                detailsVO.setTemporaryPersonVO(admissionPersonBaseVO);
            }else if(StringUtils.equals(type, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04)){
                TemporaryAdmissionCarBaseVO admissionCarBaseVO = temporaryAdmissionService.findByCar(new TemporaryAdmissionIdDTO(constructionWorkAccessMonadBean.getAssociationObjId()));
                detailsVO.setTemporaryCarVO(admissionCarBaseVO);
            }

            if(StringUtils.isNotBlank(constructionWorkAccessMonadBean.getConstructionWorkObjId())){
                String name = constructionWorkService.findNameByObjId(constructionWorkAccessMonadBean.getConstructionWorkObjId());
                detailsVO.setConstructionWorkName(name);
            }
        }
        return detailsVO;
    }

    /**
     * 分页查询待审批列表
     *
     * @param dto 查询条件
     * @return 审批单信息
     */
    @Override
    public IPage<ConstructionWorkAccessMonadPageVO> pageByPendingApproval(ConstructionWorkAccessMonadPageDTO dto) throws GeneralSimpleException {
        List<String> accessStatusList = Lists.newArrayList();
        // 待审批
        accessStatusList.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02);
        return page(dto, accessStatusList);
    }

    /**
     * 分页查询已审批列表
     *
     * @param dto 查询条件
     * @return 审批单信息
     */
    @Override
    public IPage<ConstructionWorkAccessMonadPageVO> pageByApproval(ConstructionWorkAccessMonadPageDTO dto) throws GeneralSimpleException {
        List<String> accessStatusList = Lists.newArrayList();
        // 已审批
        accessStatusList.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);
        // 驳回
        accessStatusList.add(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03);
        return page(dto, accessStatusList);
    }

    /**
     * 统计待审批单子数量
     */
    @Override
    public void countPendingApproval() {
        List<String> allUserIds = warnWebSocketService.getAllUserIds();
        if(CollectionUtils.isNotEmpty(allUserIds)){
            allUserIds.forEach(userId -> {
                List<String> workIdList = Lists.newArrayList();
                boolean headOffice = false;
                try {
                    headOffice = userService.checkHeadOffice(userId);
                
                    if(!headOffice){
                        UserBaseInfoVO userBaseInfoVO = userService.findById(userId);
                        if(Objects.nonNull(userBaseInfoVO)){
                            boolean projectDepartment = userService.checkProjectDepartment(userBaseInfoVO.getOrgId());
                            if(projectDepartment){
                                // 项目部
                                String departmentOrgIdByOrgId = orgService.findDepartmentOrgIdByOrgId(userBaseInfoVO.getOrgId());
                                if(StringUtils.isNotBlank(departmentOrgIdByOrgId)){
                                    List<String> dataPermissionDepartmentOrgId = orgService.getDataPermissionDepartmentOrgId(departmentOrgIdByOrgId);
                                    if(CollectionUtils.isNotEmpty(dataPermissionDepartmentOrgId)){
                                        workIdList = constructionWorkService.findWorkIdByProjectDepartmentObjIdIn(dataPermissionDepartmentOrgId);
                                    }
                                }
                            }else{
                                // 非项目部，并且是总包
                                boolean generalContractingUnit = userService.checkGeneralContractingUnit(userId);
                                if(generalContractingUnit){
                                    workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId(userBaseInfoVO.getOrgId());
                                }else{
                                    String departmentOrgIdByOrgId = orgService.findDepartmentOrgIdByOrgId(userBaseInfoVO.getOrgId());
                                    if(StringUtils.isNotBlank(departmentOrgIdByOrgId)){
                                        List<String> dataPermissionDepartmentOrgId = orgService.getDataPermissionDepartmentOrgId(departmentOrgIdByOrgId);
                                        if(CollectionUtils.isNotEmpty(dataPermissionDepartmentOrgId)){
                                            workIdList = constructionWorkService.findWorkIdByProjectDepartmentObjIdIn(dataPermissionDepartmentOrgId);
                                        }
                                    }
                                }
                            }
                        }
                        if(CollectionUtils.isEmpty(workIdList)){
                            return;
                        }
                    }
                } catch (Exception e){
                    log.info("获取用户信息异常", e);
                }
                
                Integer count = this.lambdaQuery()
                        .eq(ConstructionWorkAccessMonadBean::getAccessStatus, BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)
                        .in(!headOffice, ConstructionWorkAccessMonadBean::getConstructionWorkObjId, workIdList)
                        .count();
                count = count == null ? 0 : count;
                Integer finalCount = count;
          
                sendWebSocketWarnCount(userId, finalCount);
            });
        }
    }

    /**
     * 保存审批单
     *
     * @param constructionWorkAccessMonadBean 审批单实体
     * @return 保存状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveBean(ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean) {
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            constructionWorkAccessMonadBean.setApprovalNumber(getNextApprovalNumber());
            return save(constructionWorkAccessMonadBean);
        }
        return false;
    }

    /**
     * 根据审批单ID查询审批单
     *
     * @param accessMonadObjId 审批单ID
     * @return 审批状态
     */
    @Override
    public ConstructionWorkAccessMonadBean findByObjId(String accessMonadObjId) {
        ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = this.lambdaQuery().eq(ConstructionWorkAccessMonadBean::getObjId, accessMonadObjId).one();
        if(Objects.nonNull(constructionWorkAccessMonadBean)){
            return constructionWorkAccessMonadBean;
        }
        return null;
    }

    /**
     * 根据审批单ID更新审批单状态
     *
     * @param accessStatus 审批状态
     * @param objId        审批单ID
     * @return 更新状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateAccessStatusByObjId(String accessStatus, String objId) {
        return this.lambdaUpdate().set(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .eq(ConstructionWorkAccessMonadBean::getObjId, objId)
                .update();
    }

    /**
     * 查询人员ID
     *
     * @param personObjIdList  关联ID
     * @param approvalFormType 审批单类型
     * @param accessStatus     准入状态
     * @param nowDate 当前时间
     * @return 关联ID
     */
    @Override
    public List<String> findPersonObjIdByAssociationObjIdInAndTypeAndAccessStatus(List<String> personObjIdList, String approvalFormType, String accessStatus, Date nowDate) {
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery().in(ConstructionWorkAccessMonadBean::getAssociationObjId, personObjIdList)
                .eq(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .eq(ConstructionWorkAccessMonadBean::getType, approvalFormType)
                .le(ConstructionWorkAccessMonadBean::getCycleStart, nowDate)
                .ge(ConstructionWorkAccessMonadBean::getCycleEnd, nowDate)
                
                .list();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            return accessMonadBeanList.stream().map(ConstructionWorkAccessMonadBean::getAssociationObjId).collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 查询审批单ID
     *
     * @param workIdList   工程ID
     * @param typeList     审批单类型
     * @param accessStatus 准入状态
     * @return 审批单ID
     */
    @Override
    public List<String> findObjIdByWorkIdInAndTypeInAndAccessStatus(List<String> workIdList, List<String> typeList, String accessStatus) {
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery()
                .in(ConstructionWorkAccessMonadBean::getConstructionWorkObjId, workIdList)
                .in(ConstructionWorkAccessMonadBean::getType, typeList)
                .eq(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .list();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            return accessMonadBeanList.stream().map(ConstructionWorkAccessMonadBean::getObjId).collect(Collectors.toList());
        }

        return null;
    }

    /**
     * 查询审批单ID
     *
     * @param typeList     审批单类型
     * @param accessStatus 准入状态
     * @return 审批单ID
     */
    @Override
    public List<String> findObjIdByTypeInAndAccessStatus(List<String> typeList, String accessStatus) {
        List<ConstructionWorkAccessMonadBean> accessMonadBeanList = this.lambdaQuery()
                .in(ConstructionWorkAccessMonadBean::getType, typeList)
                .eq(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .list();
        if(CollectionUtils.isNotEmpty(accessMonadBeanList)){
            return accessMonadBeanList.stream().map(ConstructionWorkAccessMonadBean::getObjId).collect(Collectors.toList());
        }

        return null;
    }

    /**
     * 更新审批单信息
     *
     * @param accessStatus 审批状态
     * @param cycleStart   开始时间
     * @param cycleEnd     结束时间
     * @param constructionWorkObjId        工程
     * @param objId        审批单ID
     * @return 状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateAccessStatusAndCycleStartAndCycleEndAndConstructionWorkObjIdByObjId(
            String accessStatus, Date cycleStart, Date cycleEnd, String constructionWorkObjId, String objId) {
        return this.lambdaUpdate().set(ConstructionWorkAccessMonadBean::getAccessStatus, accessStatus)
                .set(ConstructionWorkAccessMonadBean::getCycleStart, cycleStart)
                .set(ConstructionWorkAccessMonadBean::getCycleEnd, cycleEnd)
                .set(ConstructionWorkAccessMonadBean::getConstructionWorkObjId, constructionWorkObjId)
                .eq(ConstructionWorkAccessMonadBean::getObjId, objId).update();
    }

    /**
     * 发送webSocket告警统计
     * @param userId 用户信息
     */
    private void sendWebSocketWarnCount(String userId, Integer count){
        WarnCountVO warnCountVO = new WarnCountVO();
        warnCountVO.setMsgType(BaseCodeConstants.CodeType_WebSocketMsgType.KEY_WebSocketMsgType03);
        warnCountVO.setMsgCount(String.valueOf(count));
        warnWebSocketService.sendMessage(JSON.toJSONString(warnCountVO), Collections.singletonList(userId));
    }

    /**
     * 分页查询
     * @param dto 查询条件
     * @param accessStatusList 审批状态
     * @return 审批单信息
     */
    private IPage<ConstructionWorkAccessMonadPageVO> page(ConstructionWorkAccessMonadPageDTO dto, List<String> accessStatusList) throws GeneralSimpleException {
        IPage<ConstructionWorkAccessMonadBean> constructionWorkBeanIPage = new Page<>(dto.getPage(), dto.getSize());

        boolean headOffice = userService.checkHeadOffice();
        List<String> workIdList = Lists.newArrayList();
        if(!headOffice){
            boolean generalContractingUnit = userService.checkGeneralContractingUnit();
            if(generalContractingUnit){
                workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId();
                if(CollectionUtils.isEmpty(workIdList)){
                    log.info("摄像机查询，没有查询到总包的工程");
                    return new Page<>(dto.getPage(), dto.getSize());
                }
            }else{
                List<String> dataPermissionDepartmentOrgId = orgService.getDataPermissionDepartmentOrgId();
                if(CollectionUtils.isNotEmpty(dataPermissionDepartmentOrgId)){
                    workIdList = constructionWorkService.findWorkIdByProjectDepartmentObjIdIn(dataPermissionDepartmentOrgId);
                }
            }
            
            if(CollectionUtils.isEmpty(workIdList)){
                return new Page<>(dto.getPage(), dto.getSize());
            }
        }
        
        List<String> userIdList = null;
        if(StringUtils.isNotBlank(dto.getSearchStr())){
            userIdList = userService.findUserIdByFullName(dto.getSearchStr());
        }

        List<String> finalUserIdList = userIdList;
        IPage<ConstructionWorkAccessMonadBean> accessMonadBeanIPage = this.lambdaQuery()
                .in(!headOffice, ConstructionWorkAccessMonadBean::getConstructionWorkObjId, workIdList)
                .eq(StringUtils.isNotEmpty(dto.getType()), ConstructionWorkAccessMonadBean::getType, dto.getType())
                .and(StringUtils.isNotEmpty(dto.getSearchStr()), 
                        w -> w.like(ConstructionWorkAccessMonadBean::getApprovalNumber, dto.getSearchStr())
                                .or()
                                .in(CollectionUtils.isNotEmpty(finalUserIdList), ConstructionWorkAccessMonadBean::getCreateUser, finalUserIdList))
                .eq(StringUtils.isNotEmpty(dto.getType()), ConstructionWorkAccessMonadBean::getType, dto.getType())
                .in(CollectionUtils.isNotEmpty(accessStatusList), ConstructionWorkAccessMonadBean::getAccessStatus, accessStatusList)
                .orderByDesc(ConstructionWorkAccessMonadBean::getApprovalNumber)
                .orderByDesc(ConstructionWorkAccessMonadBean::getObjId)
                .page(constructionWorkBeanIPage);

        IPage<ConstructionWorkAccessMonadPageVO> pageVOIPage = new Page<>(accessMonadBeanIPage.getCurrent(), accessMonadBeanIPage.getSize(), accessMonadBeanIPage.getTotal());
        List<ConstructionWorkAccessMonadPageVO> pageVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accessMonadBeanIPage.getRecords())) {
            List<String> createUserList = Lists.newArrayList(); 
            List<String> createUserOrgIdList = Lists.newArrayList();
            accessMonadBeanIPage.getRecords().forEach(accessMonadBean -> {
                if(StringUtils.isNotBlank(accessMonadBean.getCreateUser())){
                    createUserList.add(accessMonadBean.getCreateUser());
                }
                if(StringUtils.isNotBlank(accessMonadBean.getCreateUserOrgId())){
                    createUserOrgIdList.add(accessMonadBean.getCreateUserOrgId());
                }
            });
            
            // 人员信息
            Map<String, String> userMap = userService.findNameByIdIn(createUserList);

            // 单位信息
            List<OrgBean> orgBeanList = orgService.lambdaQuery().in(OrgBean::getId, createUserOrgIdList).list();
            Map<String, String> orgMap = Maps.newHashMap();
            if(CollectionUtils.isNotEmpty(orgBeanList)){
                orgMap = orgBeanList.stream().collect(Collectors.toMap(OrgBean::getId, OrgBean::getName));
            }

            Map<String, String> finalOrgMap = orgMap;
            accessMonadBeanIPage.getRecords().forEach(accessMonadBean -> {
                ConstructionWorkAccessMonadPageVO accessMonadPageVO = new ConstructionWorkAccessMonadPageVO();
                BeanUtils.copyProperties(accessMonadBean, accessMonadPageVO);

                // 人员名称
                if(StringUtils.isNotBlank(accessMonadBean.getCreateUser())){
                    accessMonadPageVO.setCreateUserName(userMap.get(accessMonadBean.getCreateUser()));
                }

                // 发起单位名称
                if(StringUtils.isNotBlank(accessMonadBean.getCreateUserOrgId())){
                    if(finalOrgMap.containsKey(accessMonadBean.getCreateUserOrgId())){
                        accessMonadPageVO.setCreateUserOrgName(finalOrgMap.get(accessMonadBean.getCreateUserOrgId()));
                    }else{
                        accessMonadPageVO.setCreateUserOrgName(orgService.findOrgNameByOrgId(accessMonadBean.getCreateUserOrgId()));
                    }
                }

                String name = constructionWorkService.findNameByObjId(accessMonadBean.getConstructionWorkObjId());
                accessMonadPageVO.setConstructionWorkName(name);

                // 驳回意见
                if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03)){
                    accessMonadPageVO.setOpinion(accessMonadBean.getOpinion());    
                }
                
                pageVOList.add(accessMonadPageVO);
            });
            pageVOIPage.setRecords(pageVOList);
        }
        return pageVOIPage;
    }
}
